#pragma once
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include <chrono>
#include <nlohmann/json.hpp>
#include "database/redis_pool.h"

namespace cpp_backend {
namespace framework {

/**
 * @brief 服务实例信息
 */
struct ServiceInstance {
    std::string service_name;   // "PingService"
    std::string host;           // "127.0.0.1"
    int port;                   // 9001
    std::string instance_id;    // "ping-service-12345"
    int weight = 10;            // 负载均衡权重
    int64_t register_time = 0;  // 注册时间戳
    int64_t heartbeat_time = 0; // 最后心跳时间
    
    /**
     * @brief 序列化为JSON字符串
     */
    std::string to_json() const {
        nlohmann::json j;
        j["service_name"] = service_name;
        j["host"] = host;
        j["port"] = port;
        j["instance_id"] = instance_id;
        j["weight"] = weight;
        j["register_time"] = register_time;
        j["heartbeat_time"] = heartbeat_time;
        return j.dump();
    }
    
    /**
     * @brief 从JSON字符串反序列化
     */
    static ServiceInstance from_json(const std::string& json_str) {
        auto j = nlohmann::json::parse(json_str);
        ServiceInstance instance;
        instance.service_name = j["service_name"];
        instance.host = j["host"];
        instance.port = j["port"];
        instance.instance_id = j["instance_id"];
        instance.weight = j.value("weight", 10);
        instance.register_time = j.value("register_time", 0L);
        instance.heartbeat_time = j.value("heartbeat_time", 0L);
        return instance;
    }
};

/**
 * @brief 服务注册中心（基于Redis）
 * 
 * Redis数据结构：
 * - HASH: service:{ServiceName}:instances
 *   字段：instance_id -> ServiceInstance JSON
 * - STRING: service:heartbeat:{instance_id}
 *   TTL: 30秒，用于健康检查
 */
class ServiceRegistry {
public:
    explicit ServiceRegistry(database::RedisPool* redis_pool)
        : redis_pool_(redis_pool) {}
    
    ~ServiceRegistry() = default;
    
    /**
     * @brief 注册服务实例
     * 
     * Redis操作：
     * 1. HSET service:PingService:instances ping-service-1 '{...}'
     * 2. SETEX service:heartbeat:ping-service-1 30 "alive"
     * 
     * @param instance 服务实例信息
     * @return 是否注册成功
     */
    bool register_service(const ServiceInstance& instance);
    
    /**
     * @brief 注销服务实例
     * 
     * Redis操作：
     * 1. HDEL service:PingService:instances ping-service-1
     * 2. DEL service:heartbeat:ping-service-1
     * 
     * @param instance_id 实例ID
     * @return 是否注销成功
     */
    bool unregister_service(const std::string& instance_id);
    
    /**
     * @brief 服务发现：获取所有健康实例
     * 
     * 流程：
     * 1. HGETALL service:PingService:instances
     * 2. 过滤：只返回有心跳的实例（EXISTS service:heartbeat:xxx）
     * 
     * @param service_name 服务名称
     * @return 健康实例列表
     */
    std::vector<ServiceInstance> discover(const std::string& service_name);
    
    /**
     * @brief 心跳：保持实例活跃
     * 
     * Redis操作：
     * SETEX service:heartbeat:ping-service-1 30 "alive"
     * 
     * @param instance_id 实例ID
     * @return 是否心跳成功
     */
    bool heartbeat(const std::string& instance_id);
    
    /**
     * @brief 健康检查：移除过期实例
     * 
     * 定期任务（每10秒）：
     * 1. 遍历所有服务实例
     * 2. 检查心跳是否存在
     * 3. 删除过期实例
     */
    void health_check();
    
private:
    database::RedisPool* redis_pool_;
    mutable std::mutex registry_mutex_;
    
    // Redis Key生成
    std::string make_instance_key(const std::string& service_name) const {
        return "service:" + service_name + ":instances";
    }
    
    std::string make_heartbeat_key(const std::string& instance_id) const {
        return "service:heartbeat:" + instance_id;
    }
};

} // namespace framework
} // namespace cpp_backend
